﻿using log4net;
using MSDAL;
using MSWeb.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using MSDAL.Implementation;
using System.Transactions;
using MSWEB.Implementation;

namespace MSWeb.Implementation
{
    public class ScheduleCalculator
    {
        readonly ILog _loger = LogManager.GetLogger(typeof(ScheduleCalculator));
        readonly MSEntities _db;
        private readonly LessonRepository _lessonRepo;
        private readonly DataRepository _dataRepo;

        public ScheduleCalculator()
        {
            _db = new MSEntities();
            _lessonRepo = new LessonRepository();
            _dataRepo = new DataRepository();
        }

        public bool AddNewScheduleForLessons()
        {
            try
            {
                var result = _dataRepo.GetActiveStudents();
                result.ForEach(item =>
                {
                    var schedules = GetSchedulesByStudentId(item.IDUcznia);
                    schedules.ForEach(schedule =>
                    {
                        AddSequentionalRepatedLessons(schedule.IDPowtorzenia);
                    });
                });
                return true;
            }
            catch (Exception ex)
            {
                _loger.Error(ex.Message);
                return false;
            }
        }

        public List<PowtorzeniaLekcji> GetSchedulesByStudentId(int studentId)
        {
            return _db.PowtorzeniaLekcji
                .Where(i => i.IDUcznia == studentId 
                    && i.DataWaznosci > DateTime.Now.Date)
                .ToList();
        }

        public bool AddScheduleWithLessonInTransaction(NewScheduleModel schedule)
        {
            using (var scope = new TransactionScope())
            {
                var answer = CreateNewEntries(schedule);
                if (answer == 0)
                    throw new Exception("Blad tworzenia powtorzenia lekcji");
                if (AddSequentionalRepatedLessons(answer) == false)
                    throw new Exception("Blad tworzenia powtorzenia lekcji");
                scope.Complete();
            }
            return true;
        }

        public List<PowtorzeniaLekcji> GetActiveRepeatedLessons()
        {
            return _db.PowtorzeniaLekcji
                .Where(i => i.Aktywna.Value)
                .ToList();
        }

        public List<PowtorzeniaLekcji> ReuturnListRepeatedLessonsForUser(int studentId)
        {
            return _db.PowtorzeniaLekcji
                .Where(i => i.IDUcznia == studentId && i.Aktywna == true)
                .ToList();
        }

        public int CreateNewEntries(NewScheduleModel newScheduleModel)
        {
            try
            {
                var repeatedLesson = new PowtorzeniaLekcji
                {
                    IDUcznia = newScheduleModel.IDUcznia,
                    IDNauczyciela = newScheduleModel.IDNauczyciela,
                    Czas = newScheduleModel.DataPoczatkowaICzas,
                    IDSali = newScheduleModel.IDSali,
                    KosztLekcji = newScheduleModel.KosztLekcji,
                    WynagrodzenieNauczyciela = newScheduleModel.WynagrodzenieNauczyciela,
                    CzasTrwaniaLekcji = newScheduleModel.CzasTrwaniaLekcji,
                    Aktywna = true,
                    DataWaznosci = newScheduleModel.DataWaznosci.Date
                };
                var nauczyciel =
                _db.Nauczyciele
                    .FirstOrDefault(i => i.IDNauczyciela == newScheduleModel.IDNauczyciela);
                repeatedLesson.WynagrodzenieNauczyciela =
                    int.Parse(
                        nauczyciel.WynagrodzenieZaLekcje.ToString()
                    );
                _db.PowtorzeniaLekcji.Add(repeatedLesson);
                _db.SaveChanges();
                return repeatedLesson.IDPowtorzenia;
            }
            catch (Exception ex)
            {
                _loger.Error(ex.Message);
                _loger.Error(ex.InnerException);
                return 0;
            }
        }

        public bool AddSequentionalRepatedLessons(int scheduleId)
        {
            try
            {
                var schedule = _db.PowtorzeniaLekcji
                    .FirstOrDefault(i => i.IDPowtorzenia == scheduleId);
                if (schedule == null)
                    return false;
                var nowDate = schedule.Czas;
                var maxDate = new DateTime();

                if (!GetMaxDateForSchedule(scheduleId).HasValue)
                    maxDate = nowDate.Value.AddDays(31);
                else
                {
                    maxDate = GetMaxDateForSchedule(scheduleId).Value;
                }
                while ((maxDate - nowDate.Value).TotalDays > 1)
                {
                    _lessonRepo.SaveNewLesson(new NewLessonViewModel
                    {
                        CenaLekcjiNauczyciela = schedule.WynagrodzenieNauczyciela,
                        CenaLekcjiUcznia = schedule.KosztLekcji,
                        CzasTrwaniaLekcji = schedule.CzasTrwaniaLekcji,
                        CzyRozliczona = false,
                        CzyUczenL4 = false,
                        CzyZatwierdzona = false,
                        IdPowtorzenia = scheduleId,
                        IDNauczyciela = schedule.IDNauczyciela,
                        IDSali = schedule.IDSali.Value,
                        Data = nowDate,
                        IDUcznia = schedule.IDUcznia.Value,
                    });
                    nowDate = nowDate.Value.AddDays(7);                   
                }
                return true;
            }
            catch (Exception ex)
            {
                _loger.Error(ex.Message);
                return false;
            }
        }

        private DateTime? GetMaxDateForSchedule(int scheduleId)
        {
            DateTime? maxDate = _db.Lekcje
                .Where(i => i.IDPowtorzenia == scheduleId)
                .Max(i => i.Data);
            return maxDate;
        }
        private DateTime ChangeTime(DateTime dateTime, TimeSpan time)
        {
            return new DateTime(
                dateTime.Year,
                dateTime.Month,
                dateTime.Day,
                time.Hours,
                time.Minutes,
                time.Seconds,
                time.Milliseconds,
                dateTime.Kind);
        }
    }
}